home *** CD-ROM | disk | FTP | other *** search
- ;
- ; -> DiskBOOTloader <-
- ;
- ; 1990 by Duke/Level Four
- ;
- ;Notes:
- ;a) If you want to load and execute CRUNCHED proggys with this
- ; loader, you should know the address where the decruncher puts
- ; your program into memory to be sure that it won't scratch the
- ; loader-routine. Moreover you have to know that your prog
- ; will crash if you load it into its own decrunch area!
- ; To prevent such crashes, you're able to set the address
- ; of the bootloader and the address where your prog should
- ; be located after loading by changing the address at
- ; "Bootstart". !!!DON'T DECREASE THE OFFSET AT "Buffer"!!!
- ;b) How to install the bootloader on your disk (df0:):
- ; 1. assemble this loader (with MASTERSEKA)
- ; 2. bstart_boot <Return> ;calculate boot-checksum
- ; 3. ws0 <Return> ;(w)rite(s)ector on df(0)
- ; 4. BEG>start_boot<Return>
- ; 5. SECTOR>0 <Return> ;start sector 0
- ; 6. AMOUNT>2 <Return> ;write 2 sectors (1024 bytes)
- ; Now you must save the program which you want to load to the
- ; same disk on the correct tracks. You can do that with
- ; MASTERSEKA, too, by typing:
- ; 1.ri <Return> ;(r)ead (i)mage
- ; 2.FILENAME>progname<Return> ;enter name of your program here
- ; 3.BEG>$40000 <Return> ;load prog. to $40000 for example
- ; 4.END> <Return> ;load WHOLE prog. just return here
- ; 5.wt0 <Return> ;(w)rite (t)rack on df(0)
- ; 6.BEG>$40000 <Return>
- ; 7.CYLINDER>enter startcylinder here (1 cylinder=2 tracks)
- ; 8.AMOUNT>enter length of your prog in cylinders (1cyl=11264bytes)
-
- ;If you have no MASTERSEKA you can use the Amiga Mon or the C-mon
- ;to install your program and the loader on disk.
- ;Ok. Now your AMIGA should load and execute your program correctly.
- ;signed duke/l4
-
- ;MACRO-definitions
- color: macro
- move.w #\1,$180(a6)
- endm
-
- ;now we waste diskspace by using the following step-macro (but who
- ;cares ? - This bootblock is about 920 bytes long...)
-
- step: macro
- move.b floppystatus(pc),d0
- move.b d0,d1
- bclr #0,d0 ;clear DSKSTEP after setting it...STEP!
- move.b d0,(a0) ;a0=$bfd100 (CIA-B PRB)
- nop ;wait a little
- nop
- move.b d1,(a0) ;set DSKSTEP back to 1
- bsr.l timer ;wait a while
- endm
- ;Statements
- Bootstart = $20000
- ;bootstart=address of bootloader - may be changed!
-
- ;
- Buffer = Bootstart+$4000
- ;buffer=address of your decoded program - !!!DON'T DECREASE IT!!!
- ;
-
- Amount = 22
- ;amount of tracks to read - may be changed, of course!
-
- first_track = 26
- ;first track to read - may be changed, too!
- ;
-
- org $40000 ;$40000 should work without 1MB, too.
- load $40000
-
- start_boot:
- dc.b "DOS",0 ;DOS id
- dc.l 0 ;space for checksum
- dc.l $370 ;pointer to rootblock
- ;
- movem.l d0-d7/a0-a6,-(a7)
- lea bootstart,a0 ;copy bootblock to bootstart (s. above)
- lea start_boot(pc),a1
- move.w #$ff,d7 ;copy 1024 bytes
- copy_boot:
- move.l (a1)+,(a0)+
- dbf d7,copy_boot
- jmp bootstart+[start-start_boot] ;jump in loader
- ;
- ;Here the loading-routine...
-
- S:
- Start:
- lea $dff000,a6 ;coustom base
- lea s(pc),a5 ;addressoffset (bootblock MUST be pc-
- ;relative)
-
- move.w $01c(a6),oldint-s(a5)
- ori.w #$8000,oldint-s(a5)
- move.w $002(a6),olddma-s(a5)
- ori.w #$8000,olddma-s(a5)
- move.w $010(a6),oldadk-s(a5)
- ori.w #$8000,oldadk-s(a5)
- move.w #$7fff,d0
- move.w d0,$096(a6) ;switch dma's off
- move.w d0,$09a(a6) ;forbid interrupts
- move.w d0,$09c(a6) ;clear intreq
- move.w d0,$09e(a6) ;clear adkcon
-
- color 0 ;background color while loading
- move.w #$8210,$96(a6) ;diskdma on!
-
- ;select DRIVE: 3210
- moveq #%0001,d0 ;set right bit for drive 0,1,2 or 3
- bsr.l select_drive ;select drive from which you want to read
-
- bsr.l motor_on ;drivemotor on
-
- moveq #0,d0 ;move track number ->d0
- bsr.l head_pos ;move head to track 0 (orientation)
-
- bsr.l init_read ;init diskregisters
- ;
- move.w #Amount,trackct-s(a5);set trackcounter
- ;
-
- Load_tracks:
- bchg #1,$bfe001 ;switch led on/off each cylinder
- move.w track(pc),d0 ;move head to starttrack
- bsr.l head_pos
- bsr.l test_disk ;check if disk in drive
- ;
- bsr.l read_track ;read track
- bsr.l decode_track ;decode track
- ;
- addq.w #1,track-s(a5) ;next track (add/sub=increase/decrease)
- subq.w #1,trackct-s(a5);decrease trackcounter
- bne.s load_tracks
- ;
- bsr.l Motor_off ;drivemotor off
- move.l bufferpt2(pc),a0;change jump in-address at bufferpt2
- jsr (a0) ;jump in loaded program
- Exit:
- move.w Olddma(pc),$096(a6)
- move.w Oldint(pc),$09a(a6)
- move.w Oldadk(pc),$09e(a6)
- movem.l (a7)+,d0-d7/a0-a6
-
- ;Here the normal bootroutine is following. But please notice that it's
- ;now impossible for the operating-system to access its disk operations
- ;correctly, because we used the hardware in that direct way without
- ;permission of the operating-system. That's the reason why you'll see
- ;a 'not a DOS disk'-requester after returning from the loader. So you
- ;see that it would be better to jump into the reset-routine instead
- ;of accessing the following 'find resident'-routine.
-
- ;Reset your AMIGA...
- ; move.l $4.w,a6
- ; clr.l 38(a6) ;destroy chkbase to force...
- ; move.l #$fc00d2,$80.w
- ; trap #0 ;...cold reset
-
- ;...or be stupid and try the normal boot-procedure.
- move.l $4.w,a6
- lea Dosname(pc),a1
- jsr -96(a6) ;FindResident()
- move.l d0,a0
- move.l 22(a0),a0
- moveq #0,d0
- Rts
-
- dosname:dc.b "dos.library",0
- olddma: dc.w 0
- oldint: dc.w 0
- oldadk: dc.w 0
- track: dc.w first_track
- trackct:dc.w 0 ;trackcounter
-
- Init_Read:
- clr.w $24(a6) ;DSKLEN->forbid diskdma and writing
- move.w #$4489,$7e(a6) ;set standard SYNC
- move.w #$7f00,$9e(a6) ;clear ADKCON
- move.w #$9500,$9e(a6) ;set required bits
- move.w #$0002,$9c(a6) ;clear DSKBLK bit
- Rts
-
- Read_Track:
- clr.w $24(a6) ;DSKLEN->forbid diskdma
- lea trackbuff(pc),a0
- move.l a0,$20(a6) ;set DSKPTH and DSKPTL
- move.w #$9a00,$24(a6) ;enable diskdma and set amount of
- move.w #$9a00,$24(a6) ;words+2 to transfer.
-
- Wait_Dma:
- btst #1,$1f(a6) ;DSKBLK=0 ?
- beq.s Wait_Dma ;yeah=> wait
- clr.w $24(a6) ;forbid writing
- move.w #$0002,$9c(a6) ;clear DSKBLK
- Rts
-
- ;Timer A-delay
- timer: ;waits ca. 1/100 sec.
- move.b #$00,$bfde00 ;clear CRA
- move.b #$7f,$bfdd00 ;clear ICR
- move.b #$00,$bfd400 ;timer a -low
- move.b #$20,$bfd500 ;timer a -high (wait-value=$2000)
- move.b #$09,$bfde00 ;set oneshot/start
- wait_timer:
- btst #0,$bfdd00 ;test ta-bit/that clears ICR
- beq.s wait_timer
- rts
-
- Wait_ready:
- btst #5,$bfe001 ;wait for DRIVEREADY
- bne.s Wait_ready ;it's useless here, because the wait-
- Rts ;loop is long enough, but......
-
- test_disk:
- btst #2,$bfe001
- beq.s error
- Rts
- error: move.w $dff006,$dff180
- bra.s error
-
- Select_Drive:
- lea floppystatus(pc),a0
- lea motorstatus(pc),a1
- moveq #-1,d1 ;$ffffffff -> d1
- lsl.w #3,d0 ;shift selectbit to right position
- eor.b d0,d1 ;selectbit must be zero
- move.b d1,(a0) ;save byte ->floppystatus.b
- eori.b #$80,d1 ;clear DSKMOTOR-bit
- move.b d1,(a1) ;save byte ->motorstatus.b
- Rts
-
- Motor_On:
- move.b #$7f,$bfd100 ;Bits 0-6 HIGH/Bit 7 LOW
- nop
- nop
- move.b motorstatus(pc),d0
- move.b d0,$bfd100 ;DSKMOTOR and DSKSELx LOW
- bsr.l Wait_Ready
- Rts
-
- Motor_Off:
- move.b #$ff,$bfd100 ;Bits 0-7 HIGH
- nop
- nop
- move.b motorstatus(pc),d0
- ori.b #$80,d0 ;DSKMOTOR HIGH DSKSELx LOW
- move.b d0,$bfd100
- Rts
-
- ;This routine moves the r/w-head to a track with the number stored
- ;in d0. A similar routine is also used by the operating-system
- ;(at $fea3da)
-
- Head_Pos:
- lea $bfd100,a0
- lea s(pc),a5
- tst.w d0 ;track number=0?
- beq.l Move_zero ;yeah=>step to track 0
- move.w Tracknum(pc),d2 ;current track number
- cmp.w d2,d0 ;oldtrack=newtrack ?
- beq.s Head_end ;yes=>don't move head
- move.w d0,d3
- move.b Floppystatus(pc),d1
- bset #2,d1 ;select head 0 (lower side)
- btst #0,d3 ;track number even ?
- beq.s Down_Right ;yes=>head 0 is the right one
- bclr #2,d1 ;no, select head 1 (upper side)
- Down_Right:
- move.b d1,Floppystatus-s(a5)
- move.b d1,(a0)
- move.w d3,Tracknum-s(a5) ;save new track-number
- lsr.w #1,d2 ;d2=current cylinder
- lsr.w #1,d3 ;d3=new cylinder
- sub.w d3,d2 ;make difference
- bmi.s Seek_in ;diff. negativ=> step in
- beq.s Head_end
- bra.s Seek_out ;diff. positiv=> step out
- Seek_in:
- bclr #1,d1 ;step in
- move.b d1,Floppystatus-s(a5)
- neg.w d2 ;make number positive
- bra.s Step_Ok
- Seek_out:
- bset #1,d1 ;step out
- move.b d1,Floppystatus-s(a5)
- bra.s Step_Ok
- HeadStep:
- Step ;call step-macro
- Step_Ok:
- dbf d2,HeadStep
- Head_end:
- Rts
-
- Move_zero: ;move head to track zero
- move.b Floppystatus(pc),d1
- bset #2,d1
- bset #1,d1
- move.b d1,Floppystatus-s(a5)
- clr.w Tracknum-s(a5)
- Headzero:
- btst #4,$bfe001 ;test if zero
- beq.s zero1
- Step
- bra.s Headzero
- zero1:
- bclr #1,Floppystatus-s(a5)
- Step
- bset #1,Floppystatus-s(a5)
- Step
- bra.s Head_end
-
- ;
- ;This routine decodes the block-header and checks the format-sign.
- ;After this it calculates the checksum from the data-block and
- ;compares it with the checksum wich is stored in the block-header.
- ;While calculating the checksum it decodes the data block, of course.
-
- decode_track:
- move.l bufferpt(pc),a0 ;pointer to decodebuffer
- lea trackbuff(pc),a1 ;pointer to MFMbuffer
- moveq #11-1,d5 ;decode 11 blocks (-1 coz dbf)
- move.l #$55555555,d3 ;filter for tactbits
-
- decode_all_blocks:
- cmpi.w #$4489,(a1)+ ;1st sync-word found ?
- bne.s decode_all_blocks ;no=> go on searching
-
- sync_found:
- cmpi.w #$4489,(a1) ;2. sync-word found ?
- bne.s syncs_ok ;no=> all syncs skipped
- addq.w #2,a1 ;yes=>
- bra.s sync_found ;search for remaining syncs
-
- syncs_ok: ;decode infoblock
- move.l (a1)+,d0 ;odd bits
- move.l (a1)+,d1 ;even bits
- and.l d3,d0
- and.l d3,d1
- add.l d0,d0
- or.l d1,d0
-
- swap d0
- andi.w #$ff00,d0 ;mask format-sign (must be $ff)
- cmpi.w #$ff00,d0 ;right value?
- bne.s formatrerror ;no==>ERROR!
- swap d0
-
- andi.w #$ff00,d0 ;mask sector number*256
- add.w d0,d0 ;d0=d0*2 (=sector number*512)
- move.l a0,a2 ;address of decodebuffer ->a2
- adda.w d0,a2 ;calc. correct destination
-
- adda.w #40,a1 ;address of checksum ->a1
- move.l (a1)+,d4 ;decode checksum
- move.l (a1)+,d1
- and.l d3,d4
- and.l d3,d1
- add.l d4,d4
- or.l d1,d4 ;store checksum ->d4
-
- moveq #128-1,d6 ;decode 128*2 longs to 512 bytes
- moveq #0,d2 ;clear datachecksum
-
- decodeblock: ;decode datablock
- move.l 512(a1),d1 ;even bits
- move.l (a1)+,d0 ;odd bits
-
- eor.l d0,d2 ;calc checksum
- eor.l d1,d2 ;dito
-
- and.l d3,d0 ;decode longword
- and.l d3,d1
- add.l d0,d0
- or.l d1,d0
- move.l d0,(a2)+ ;store longword in buffer
- dbf d6,decodeblock ;decode next longword
-
- and.l d3,d2 ;remove tactbits
- cmp.l d4,d2 ;checksum correct ?
- bne.s chksumerror ;no=>ERROR!
- adda.w #512,a1 ;reach next block
- dbf d5,decode_all_blocks
-
- adda.w #$1600,a0 ;bufferadr.+ 1track (5632bytes)
- move.l a0,bufferpt-s(a5) ;store new address
- Rts
-
- chksumerror:
- color $f00 ;backgroundcolor red
- st chkflag-s(a5) ;set errorflag to -1
- Rts
-
- formatrerror:
- color $f00 ;backgroundcolor red
- st hdrflag-s(a5) ;set errorflag to -1
- Rts
-
- tracknum: dc.w 0
- floppystatus: dc.b 0
- motorstatus: dc.b 0
- chkflag: dc.b 0
- hdrflag: dc.b 0
- bufferpt: dc.l buffer
- bufferpt2: dc.l buffer ;here you can change the jump-
- ;in address of your prog.
- dc.b " Loader by Duke of LEVEL FOUR - ASD "
- Even
- trackbuff:
- endprg:
- blk.b 200,0 ;just to clear remaining bytes in mem
-